package main

import (
	"time"
	"log"
	"fmt"
	"os"
	"runtime"
)

func bigSlowOperation() {
	defer trace("bigSlowOperation")() // don't forget the
	// extra parentheses
	for i:=1; i<10000; i++ {
		fmt.Println(os.Stdout, i)
	}
	// ...lots of work…
	time.Sleep(10 * time.Second) // simulate slow
	// operation by sleeping
}

func trace(msg string) func() {
	start := time.Now()
	log.Printf("enter %s", msg)
	return func() {
		log.Printf("exit %s (%s)", msg,time.Since(start))
	}
}

func double(x int) (result int) {
	defer func() { fmt.Printf("double(%d) = %d\n", x,result) }()
	return x + x
}

func f(x int) {
	fmt.Printf("f(%d)\n", x+0/x) // panics if x == 0
	defer fmt.Printf("defer %d\n", x)
	f(x - 1)
}

func main() {
	// bigSlowOperation()

	_ = double(4)

	defer printStack()
	f(3)
}

func printStack() {
	var buf [4096]byte
	n := runtime.Stack(buf[:], false)
	os.Stdout.Write(buf[:n])
}
